#include "No7pch.h"
#include "Camera.h"

#include <float.h>

nmspc::Camera2::Camera2() :
	nmspc::Entity2(),
	scale_ratio(1.0l),
	scale_speed(0.1l),
	viewport_length(1.0l),
	viewport_width(1.0l),
	move_speed(0.1l),
	move_a(0.0l),
	if_scaling(false),
	if_moving_left(false),
	if_moving_right(false),
	if_moving_up(false),
	if_moving_down(false)
{
	MathTool::MatrixFactoryIn2D::generateViewTransformationMatrix(this->data[0][0], this->data[0][1]);
}

nmspc::Camera2::Camera2(const double& x, const double& y, const double& move_speed, const double& move_a, const double& scale_speed, const double& viewport_length, const double& viewport_width) :
	nmspc::Entity2(x, y),
	scale_ratio(1.0l),
	scale_speed(scale_speed),
	viewport_length(viewport_length),
	viewport_width(viewport_width),
	move_speed(move_speed),
	move_a(move_a),
	if_scaling(false),
	if_moving_left(false),
	if_moving_right(false),
	if_moving_up(false),
	if_moving_down(false)
{
	MathTool::MatrixFactoryIn2D::generateViewTransformationMatrix(this->data[0][0], this->data[0][1]);
}

void nmspc::Camera2::onEnter()
{
}

void nmspc::Camera2::onInput(const ExMessage& msg)
{
	switch (msg.message)
	{
	case WM_KEYDOWN:
		switch (msg.vkcode)
		{
		case 'a':
		case 'A':
		case VK_LEFT:
			this->if_moving_left = true;
			break;
		case 'd':
		case 'D':
		case VK_RIGHT:
			this->if_moving_right = true;
			break;
		case 'w':
		case 'W':
		case VK_UP:
			this->if_moving_up = true;
			break;
		case 's':
		case 'S':
		case VK_DOWN:
			this->if_moving_down = true;
			break;
		}
		break;
	case WM_KEYUP:
		switch (msg.vkcode)
		{
		case 'a':
		case 'A':
		case VK_LEFT:
			this->if_moving_left = false;
			break;
		case 'd':
		case 'D':
		case VK_RIGHT:
			this->if_moving_right = false;
			break;
		case 'w':
		case 'W':
		case VK_UP:
			this->if_moving_up = false;
			break;
		case 's':
		case 'S':
		case VK_DOWN:
			this->if_moving_down = false;
			break;
		}
		break;
	case WM_MOUSEWHEEL:
		if (msg.wheel >= 120)
		{
			this->if_scaling -= 1;
		}
		else if (msg.wheel <= -120)
		{
			this->if_scaling += 1;
		}
		else
		{
			this->if_scaling = 0;
		}
		break;
	}
}

void nmspc::Camera2::onUpdate(std::int32_t time_interval)
{
	static double cur_move_speed = this->move_speed;
	static double cur_scale_ratio = this->scale_ratio;
	double interval = double(time_interval);
	if (this->if_moving_left || this->if_moving_right || this->if_moving_up || this->if_moving_down)
	{
		cur_move_speed += (interval * this->move_a);
		if (this->if_moving_left)
		{
			this->data[0][0] -= cur_move_speed;
		}
		if (this->if_moving_right)
		{
			this->data[0][0] += cur_move_speed;
		}
		if (this->if_moving_up)
		{
			this->data[0][1] -= cur_move_speed;
		}
		if (this->if_moving_down)
		{
			this->data[0][1] += cur_move_speed;
		}
		MathTool::MatrixFactoryIn2D::generateViewTransformationMatrix(this->data[0][0], this->data[0][1]);
	}
	else
	{
		cur_move_speed = this->move_speed;
	}
	if (this->if_scaling != 0)
	{
		cur_scale_ratio = 1.0l;
		cur_scale_ratio += (this->scale_speed * this->if_scaling);
		if (cur_scale_ratio <= 0.5l) cur_scale_ratio = 0.5l;
		else if (cur_scale_ratio >= 2.0l) cur_scale_ratio = 2.0l;
		this->viewport_length *= cur_scale_ratio;
		this->viewport_width *= cur_scale_ratio;
		MathTool::MatrixFactoryIn2D::generateProjectionTransformationMatrix(-this->viewport_length / 2, this->viewport_length / 2, -this->viewport_width / 2, this->viewport_width / 2);
		this->if_scaling = 0;
	}
}

void nmspc::Camera2::onDraw()
{
}

void nmspc::Camera2::onExit()
{
}

void nmspc::Camera2::setPosition(const double& x, const double& y)
{
	this->nmspc::Entity2::setPosition(x, y);
	MathTool::MatrixFactoryIn2D::generateViewTransformationMatrix(x, y);
}

void nmspc::Camera2::setX(const double& x)
{
	this->nmspc::Entity2::setX(x);
	MathTool::MatrixFactoryIn2D::generateViewTransformationMatrix(x, this->data[0][1]);
}

void nmspc::Camera2::setY(const double& y)
{
	this->nmspc::Entity2::setY(y);
	MathTool::MatrixFactoryIn2D::generateViewTransformationMatrix(this->data[0][0], y);
}

double nmspc::Camera2::getViewportLength() const
{
	return this->viewport_length;
}

double nmspc::Camera2::getViewportWidth() const
{
	return this->viewport_width;
}
